package com.thuanpq.activity;

import java.lang.reflect.Method;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;

import com.android.internal.telephony.ITelephony;
import com.thuanpq.database.bus.BlacklistBus;
import com.thuanpq.entity.BlacklistItemEntity;
import com.thuanpq.global.GlobalCons;
import com.thuanpq.global.GlobalFunc;
import com.thuanpq.global.GlobalVari;

public class CallPrompt extends Activity {

	private BlacklistBus mBlacklistItemBus;

	private boolean success = false;

	private Method localMethod;
	private TelephonyManager localTelephonyManager;
	private boolean rejectBlacklist = false;
	private boolean recordCall = false;
	private long answeringPeriod = 0;

	public static void launch(Context mCon) {
		Intent prompt = new Intent(mCon, CallPrompt.class);
		prompt.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| Intent.FLAG_ACTIVITY_NO_USER_ACTION);
		mCon.startActivity(prompt);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initChild();
		invokeEvent();
	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.v("prompt onStop", "verifying success");
		if (!success)
			launch(getApplicationContext());
	}

	private void invokeEvent() {

		connectToTelephonyService(getApplicationContext());
		if (rejectBlacklist
				&& isBlacklistNumber(GlobalVari.INCOMING_CALL_NUMBER)) {
			reject();
			BlacklistItemEntity entity = mBlacklistItemBus
					.getBlacklistItemByPhone(GlobalVari.INCOMING_CALL_NUMBER);
			entity.set_lastIncomingCall(GlobalFunc.getCurrentDate());
			mBlacklistItemBus.updateBlacklistItem(entity);
		} else if (recordCall) {
			Thread myThread = new Thread(new Runnable() {
				@Override
				public void run() {

					try {
						Thread.sleep(answeringPeriod);
					} catch (InterruptedException e) {
						Log.e(GlobalVari.TAG,
								"InterruptedException: " + e.toString());
					}

					if (localTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_RINGING) {
						answer();
					}
				}
			});

			myThread.start();
		}
	}

	private void initChild() {

		mBlacklistItemBus = new BlacklistBus(this);

		rejectBlacklist = getSharedPreferences(GlobalCons.SHARED_PREF_NAME, 0)
				.getBoolean(GlobalCons.SHARED_PREF_REJECT_CALL, false);

		recordCall = getSharedPreferences(GlobalCons.SHARED_PREF_NAME, 0)
				.getBoolean(GlobalCons.SHARED_PREF_ANSWER_CALL, false);

		answeringPeriod = Long.parseLong(getSharedPreferences(
				GlobalCons.SHARED_PREF_NAME, 0).getString(
				GlobalCons.SHARED_PREF_ANSWER_PERIOD, "0"));
	}

	private boolean isBlacklistNumber(String number) {
		return mBlacklistItemBus.isBlacklistItem(number);
	}

	/**
	 * From Tedd's source
	 * http://code.google.com/p/teddsdroidtools/source/browse/ get an instance
	 * of ITelephony to talk handle calls with
	 */
	private void connectToTelephonyService(Context paramContext) {

		Log.e(GlobalVari.TAG, "connectToTelephonyService()");

		try {
			localTelephonyManager = (TelephonyManager) paramContext
					.getSystemService("phone");
			localMethod = Class.forName(
					localTelephonyManager.getClass().getName())
					.getDeclaredMethod("getITelephony", new Class[0]);
			localMethod.setAccessible(true);

		} catch (Exception e) {
			e.printStackTrace();
			Log.e(GlobalVari.TAG, "FATAL ERROR: " + e);
			finish();
		}
	}

	private boolean answeringCall() {
		try {
			// ((ITelephony) localMethod.invoke(localTelephonyManager,
			// new Object[0])).answerRingingCall();

			Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
			buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
					KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
			this.sendOrderedBroadcast(buttonDown,
					"android.permission.CALL_PRIVILEGED");

			// froyo and beyond trigger on buttonUp instead of buttonDown
			Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
			buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
					KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
			this.sendOrderedBroadcast(buttonUp,
					"android.permission.CALL_PRIVILEGED");

			Intent headSetUnPluggedintent = new Intent(
					Intent.ACTION_HEADSET_PLUG);
			headSetUnPluggedintent
					.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
			headSetUnPluggedintent.putExtra("state", 0);
			headSetUnPluggedintent.putExtra("name", "Headset");
			// TODO: Should we require a permission?
			sendOrderedBroadcast(headSetUnPluggedintent, null);

			return true;
		} catch (Exception j) {
			while (true) {
				Log.e("CallPrompt",
						": answeringCall Exception: " + j.getMessage());
				j.printStackTrace();
			}
		}
	}

	public boolean endingCall() {
		try {
			((ITelephony) localMethod.invoke(localTelephonyManager,
					new Object[0])).endCall();
			return true;
		} catch (Exception j) {
			while (true) {
				Log.e("CallPrompt", ": endCall Exception: " + j.getMessage());
				j.printStackTrace();
			}
		}
	}

	void answer() {
		success = true;
		Log.e(GlobalVari.TAG, "answer()");
		answeringCall();
		moveTaskToBack(true);
		finish();
	}

	void reject() {
		success = true;
		endingCall();
		moveTaskToBack(true);
		finish();
	}

	// we don't want to exist after phone changes to active state or goes back
	// to idle
	// we also don't want to rely on this receiver to close us after success
	BroadcastReceiver PhoneState = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (!intent.getAction().equals("android.intent.action.PHONE_STATE"))
				return;
			String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
			if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)
					|| state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
				if (!success && !isFinishing()) {
					// no known intentional dismissal and not already finishing
					// need to finish to avoid handing out after missed calls
					Log.v("call start or return to idle",
							"no user input success - closing the prompt");
					success = true;// so re-start won't fire
					finish();
				}
			}

			return;

		}
	};

	// i think this isn't in 1.5, we're also using 2.0 service methods
	@Override
	public void onBackPressed() {
		super.onBackPressed();
		success = true;
	}
}
